package com.wei.czz.framework.common.manager;

import com.wei.czz.common.constant.Constant;
import com.wei.czz.common.constant.EntityConstant;
import com.wei.czz.common.dto.admin.DictDto;
import com.wei.czz.common.dto.common.dict.DictPageEnumDto;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.common.dict.DictEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.CacheKeyUtils;
import com.wei.czz.common.utils.CopyUtils;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.framework.common.helper.CacheHelper;
import com.wei.czz.framework.common.handler.DebounceHandler;
import com.wei.czz.framework.common.handler.redis.RedisHashHandler;
import com.wei.czz.common.vo.common.dict.DictVo;
import com.wei.czz.common.vo.common.dict.DictFormVo;
import com.wei.czz.framework.common.entity.DictEntity;
import com.wei.czz.framework.common.service.DictService;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-12-07 14:44:27
 * className: DictManager
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class DictManager {

    private static final Logger log = LoggerFactory.getLogger(DictManager.class);

    private final DictService dictService;

    private final RedisHashHandler redisHashHandler;

    private final CacheHelper cacheHelper;

    private final DebounceHandler debounceHandler;

    public void saveDict(DictVo dictVo) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        DictEnum dictEnum = DictEnum.getDict(dictVo.getType());
        if (dictEnum == null) {
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "您保存的字典类型不存在，请确认");
        }
        if (!dictEnum.getMultiFlag()) {
            /*
                保存的字典数据只能添加一次，需要校验是否存在相同字典
             */
            List<DictEntity> dictList = dictService.findList(dictEnum);
            if (!dictList.isEmpty()) {
                log.info("已存在系统字典，无法重复添加");
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "您保存的字典数据已存在，请确认");
            }
        }

        // 映射
        DictEntity dict = CopyUtils.map(dictVo, DictEntity.class);
        dict.setId(null)
                .setStatus(CommonEnum.ZERO.getValue())
                .setDeleteStatus(CommonEnum.ZERO.getValue())
                .setUpdateTime(date)
                .setUpdateUser(StringUtils.EMPTY)
                .setUpdateUserId(CommonEnum.ZERO.getLongValue())
                .setCreateTime(date)
                .setCreateUser(userPo.getUsername())
                .setCreateUserId(userPo.getUserId());
        dictService.saveOrEdit(dict);


        /*
            添加缓存
         */
        String cacheKey = CacheKeyUtils.getRedisHashKey(EntityConstant.DICT);
        String valueKey = dict.getType().toString();
        if (dictEnum.getMultiFlag()) {
            // 允许重复系统字典，直接删除缓存
            redisHashHandler.delete(cacheKey, valueKey);
        } else {
            // 只有是单个系统字典，才直接添加缓存
            redisHashHandler.put(cacheKey, valueKey, dict);
        }
    }

    public PageDto<DictDto> getPageDictList(DictFormVo dictFormVo) {
        // 获取请求用户主键
        Long optUserId = SecurityUtils.getUserId();

        /*
            获取页面表单对象
         */
        String cacheKey = CacheKeyUtils.getParamCacheKey(EntityConstant.DICT);
        cacheHelper.cache(cacheKey, dictFormVo);

        /*
            分页查询字典
         */
        PageDto<DictEntity> pageDto = dictService.getPageDictList(dictFormVo);
        if (pageDto.isEmpty()) {
            return pageDto.rebuild();
        }

        List<DictEntity> dictList = pageDto.getList();

        List<DictDto> list = CopyUtils.mapList(dictList, dict -> {
            DictDto dictDto = CopyUtils.map(dict, DictDto.class);

            String dictName = DictEnum.findDictName(dict.getType());
            dictDto.setName(dictName);

            return dictDto;
        });

        // 封装返回
        return pageDto.rebuild(list);
    }

    public DictPageEnumDto getDictPageParam() {
        // 获取请求用户主键
        Long optUserId = SecurityUtils.getUserId();

        /*
            获取页面表单对象
         */
        String cacheKey = CacheKeyUtils.getParamCacheKey(EntityConstant.DICT);
        DictFormVo dictFormVo = cacheHelper.get(cacheKey, DictFormVo.class);

        DictPageEnumDto dictPageEnumDto = new DictPageEnumDto();
        dictPageEnumDto.setTypeList(DictEnum.getDictTypeList())
                .setStatusList(CommonEnum.getStatusList())
                .setDictFormVo(dictFormVo);
        return dictPageEnumDto;
    }

    public void updateDict(DictVo dictVo) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        DictEnum dictEnum = DictEnum.getDict(dictVo.getType());
        if (dictEnum == null) {
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "字典类型不存在，请确认");
        }
        if (!dictEnum.getMultiFlag()) {
            /*
                保存的字典数据只能添加一次，需要校验是否存在相同字典
             */
            List<DictEntity> dictList = dictService.findList(dictEnum);
            long count = dictList.stream().filter(dict -> !dict.getId().equals(dictVo.getId()))
                    .count();
            if (count > 0) {
                log.info("字典已存在，修改失败");
                throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "您修改的字典数据已存在，请确认");
            }
        }

        /*
            删除缓存
         */
        String cacheKey = CacheKeyUtils.getRedisHashKey(EntityConstant.DICT);
        String valueKey = dictEnum.getStringValue();
        redisHashHandler.delete(cacheKey, valueKey);

        /*
            修改字典
         */
        // 映射
        DictEntity dict = CopyUtils.map(dictVo, DictEntity.class);
        dict.setUpdateTime(date)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getUserId());
        dictService.saveOrEdit(dict);

        // 延时双删
        Runnable runnable = () -> {
            // 删除缓存
            redisHashHandler.delete(cacheKey, valueKey);
        };
        debounceHandler.debounceRun(runnable, cacheKey + Constant.SPLIT + valueKey, 2, TimeUnit.SECONDS);
    }

    public void updateDictStatus(Long id, Integer status) {
        // 获取操作用户
        UserPo userPo = SecurityUtils.getUser();
        Date date = new Date();

        /*
            获取字典
         */
        DictEntity dict = dictService.get(id);

        /*
            删除缓存
         */
        // 操作Redis缓存，删除字典缓存数据
        String cacheKey = CacheKeyUtils.getRedisHashKey(EntityConstant.DICT);
        String valueKey = dict.getType().toString();
        redisHashHandler.delete(cacheKey, valueKey);

        /*
            修改字典
         */
        DictEntity updateDict = new DictEntity();
        updateDict.setId(id)
                .setStatus(status)
                .setUpdateTime(date)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getUserId());
        dictService.saveOrEdit(updateDict);

        // 延时双删
        Runnable runnable = () -> {
            // 删除缓存
            redisHashHandler.delete(cacheKey, valueKey);
        };
        debounceHandler.debounceRun(runnable, cacheKey + Constant.SPLIT + valueKey, 2, TimeUnit.SECONDS);
    }

    public void deleteDict(List<Long> idList) {

        /*
            获取字典
         */
        List<DictEntity> dictList = dictService.getList(idList);
        if (dictList.isEmpty()) {
            throw new CzzException(ResultEnum.REFRESH);
        }

        /*
            删除字典
         */
        dictService.delete(idList);

        /*
            删除缓存
         */
        String cacheKey = CacheKeyUtils.getRedisHashKey(EntityConstant.DICT);
        List<String> valueKeyList = CopyUtils.mapList(dictList, dict -> dict.getType().toString());
        redisHashHandler.delete(cacheKey, valueKeyList);

    }

}
